# steam_data_pipeline.py

import os
import json
import logging
import datetime
from typing import List, Dict, Any

from steam_topselling_scraper import SteamTopSellingScraper
from steamcharts_client import SteamChartsClient
from steam_api_client import SteamAPIClient     # 新增：导入 API 客户端
from models import TopSellingGame
import brotli

import matplotlib.pyplot as plt

# ─── 日志配置 ─────────────────────────────────────────────────────────────
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)


def ensure_dir(path: str):
    """如果文件夹不存在就创建。"""
    if not os.path.exists(path):
        os.makedirs(path)


def slice_player_data_by_days(
    data: List[tuple],
    days: int
) -> List[tuple]:
    """
    把完整的 (datetime, players) 列表切片，返回最近 N 天的数据。
    假设 data 已按时间升序排列。
    """
    cutoff = datetime.datetime.now() - datetime.timedelta(days=days)
    return [(dt, cnt) for dt, cnt in data if dt >= cutoff]


def plot_and_save(
    dt_cnt_list: List[tuple],
    appid: int,
    game_name: str,
    window_label: str,
    output_dir: str
) -> str:
    """
    将 dt_cnt_list 画成折线图，标题显示游戏名称，保存为 PNG 文件。
    Args:
      - dt_cnt_list: List[(datetime, int)]，按时间升序排列
      - appid: Steam AppID（文件名中保留一份以防重名）
      - game_name: 游戏名称（用于图表标题）
      - window_label: 窗口标签，如 "7d"、"30d"、"90d"、"all"
      - output_dir: 存图的目录
    Returns:
      - relative_path: 保存文件的相对路径（供前端引用）
    """
    if not dt_cnt_list:
        logging.warning(f"AppID={appid} 的窗口 {window_label} 没有数据，跳过绘图。")
        return ""

    dates = [dt for dt, _ in dt_cnt_list]
    counts = [cnt for _, cnt in dt_cnt_list]

    plt.figure(figsize=(8, 4))
    plt.plot(dates, counts, linewidth=1.0)
    plt.title(f"{game_name} - 最近{window_label}")  # 标题改为游戏名称
    plt.xlabel("日期")
    plt.ylabel("在线玩家数")
    plt.tight_layout()
    plt.grid(True)

    # 保存路径示例： charts/123456_7d.png
    safe_name = game_name.replace(" ", "_")
    filename = f"{appid}_{safe_name}_{window_label}.png"
    full_path = os.path.join(output_dir, filename)
    plt.savefig(full_path, dpi=150)
    plt.close()

    logging.info(f"已保存折线图：{full_path}")
    # 为了前端方便，统一使用正斜杠
    return f"{output_dir}/{filename}"


def main():
    # ─── 配置区 ─────────────────────────────────────────────────────────────
    TOP_N = 100  # 想拉取的热销榜前 N 名

    # 定义图和 JSON 的输出目录
    CHART_DIR = "charts"
    DATA_DIR = "data"
    ensure_dir(CHART_DIR)
    ensure_dir(DATA_DIR)

    # 1) 拉取热销榜前 TOP_N，包含 price/discount/review_percent/review_total
    scraper = SteamTopSellingScraper(language="schinese", country_code="CN")
    logging.info(f"开始拉取热销榜前 {TOP_N} 名 ...")
    top_games: List[TopSellingGame] = scraper.get_top_selling_via_search(
        start=0, count=TOP_N
    )
    if not top_games:
        logging.error("未能获取任何热销榜数据，退出。")
        return

    # 2) 初始化 API 客户端 & Charts 客户端
    api_client = SteamAPIClient(country_code="CN", language="schinese")  # 用于获取搜索接口没提供的字段
    charts_client = SteamChartsClient()

    summary_list: List[Dict[str, Any]] = []

    # 3) 对每个游戏依次获取 API 补全、在线人数历史 & 画图
    for game in top_games:
        # 从搜索接口获取到的基础字段
        record: Dict[str, Any] = {
            "rank": game.rank,
            "appid": game.appid,
            "name": game.name,
            "price": game.price,
            "discount_percent": game.discount_percent,
            # 游戏商店 URL
            "store_url": f"https://store.steampowered.com/app/{game.appid}/",
            # 好评相关（均来自搜索接口）
            "review_percent": game.review_percent,
            "review_total": game.review_total,
            "charts": {}
        }

        # —— 从 appdetails API 补全搜索接口里没有提供的字段 ——
        details = api_client.get_game_details(game.appid)
        if details:
            record.update({
                "release_date": details.release_date,              # 发布日期
                "is_free": details.is_free,                        # 是否免费
                "initial_price": details.initial_price,            # 折前原价
                # API 好评率/总数，可与搜索接口字段对比或保留
                "recommendation_percent": details.recommendation_percent,
                "recommendation_total": details.recommendation_total,
                "genres": details.genres,                          # 游戏类型列表
                "short_description": details.short_description,    # 简短描述
                "header_image_url": details.header_image_url       # 头图 URL
            })

        # —— 拿在线人数历史并画图 ——
        history = charts_client.get_player_count_data(game.appid)
        if history:
            window_sizes = [("7d", 7), ("30d", 30), ("90d", 90), ("all", None)]
            for label, days in window_sizes:
                subset = history if days is None else slice_player_data_by_days(history, days)
                img_path = plot_and_save(
                    dt_cnt_list=subset,
                    appid=game.appid,
                    game_name=game.name,
                    window_label=label,
                    output_dir=CHART_DIR
                )
                if img_path:
                    record["charts"][label] = img_path

        summary_list.append(record)

    # 4) 将 summary_list 写入 JSON
    json_path = os.path.join(DATA_DIR, "top_selling_summary.json")
    with open(json_path, "w", encoding="utf-8") as f:
        json.dump(summary_list, f, ensure_ascii=False, indent=2)
    logging.info(f"已生成汇总文件：{json_path}")


if __name__ == "__main__":
    main()
